#include <iostream>
#include <stdio.h>
#include <exception>
#include <array>
#include <vector>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm> //STL中的算法
#include <exception> //异常类的头文件
#include <fstream>   //读写文件
#include <pthread.h>
#include <linux/input.h>
#include <thread>
#include <mutex>
#include "font.h"

using namespace std;
extern int show_anybmp(int w,int h,int x,int y,const char *bmpname);
struct pos
{
	int x; //一节蛇身左上角x坐标
	int y; //一节蛇身左上角y坐标
};

int ts_x; //保存触摸屏x坐标
int ts_y; //保存触摸屏y坐标
int tsfd; //保存触摸屏的文件描述符


class Snake {
public:
	void init()
	{
		body.clear();
		direction=5,length=3,speed=500*400;
		body.push_back({0,0}); // 初始位置
		body.push_back({20,0});
		head={40,0};
		body.push_back(head);
	}

    void setdirection(int _newdirection)
	{
		direction = _newdirection;
	}

	void setspeed(int _speed)
	{
		if(_speed == 500*100 && (speed == 500*400 || speed == 500*300))//减速
			speed += _speed;
		else if(_speed == -500*100 && (speed == 500*400 || speed == 500*500))//加速
			speed += _speed;
		else
			speed = speed;
	}

	void show_speed()
	{
		cout << "speed:" << speed << endl;
	}
    
	void move()
	{
		//判断移动方向
		if(direction==1)//上
		{
			head.y-=20;
		}
		if(direction==2)//下
		{
			head.y+=20;
		}
		if(direction==4)//左
		{
			head.x-=20;
		}
		if(direction==5)//右
		{
			head.x+=20;
		}

		//判断x是否超标
		if(head.y>=480||head.y<0||head.x<0||head.x>=480)
		{
			//head.y=0;
			cout<<"对不起，蛇身移动超范围，游戏结束"<<endl;
			pthread_exit(NULL);
		}
		//保存新的蛇头到容器中
		body.push_back(head);
		//把蛇尾填充成白色图片，从容器中删除蛇尾
		struct pos &temppos=body.front();
		show_anybmp(20,20,temppos.x,temppos.y,"./gz.bmp");
		body.erase(body.begin());
		//遍历容器snakelist刷图，就可以让蛇身动起来
		for(auto curpos:body)
		{
			show_anybmp(20,20,curpos.x,curpos.y,"./red.bmp");	
		}
		usleep(speed);
	}

private:
    vector<struct pos> body; //容器保存蛇身
	struct pos head; //蛇头
    int direction; //移动方向
	int newdirection;
	int speed; //速度
    int length; //蛇长度
};


class Game {
public:
    Game() : score(0), isGameOver(false),state(0) {}

    void init() //游戏初始化
	{
		//显示游戏背景
		show_anybmp(800,480,0,0,"./ui.bmp");
		show_anybmp(80,80,600,185,"./ksyx.bmp");
		snake.init();
		state=0;
	}

    void update() //更新游戏界面
	{
		if(state==1)
		snake.move();
	}

	void input_diretion(int _direction)//改变蛇的方向
	{
		snake.setdirection(_direction);
	}

	void input_speed(int _speed)//改变蛇的速度
	{
		snake.setspeed(_speed);
	}

	void show_snakespeed()
	{
		snake.show_speed();
	}

	void setstate()//开始或暂停
	{
		if(state)
		{
			state=0;
			cout<<"暂停"<<endl;
		}
		else
		{
			cout<<"开始"<<endl;
			state=1;
		}
	}

private:
    Snake snake;
    //pos food;
    int score;
	int state;
    bool isGameOver;
};
Game game1;

//线程获取坐标
void *readts(void *argv)
{
	//定义结构体存放坐标值
	struct input_event myevent;
	while(1)
	{
		//读取触摸屏坐标
		read(tsfd,&myevent,sizeof(myevent));
		//判断x,y打印出来
		if(myevent.type==EV_ABS) //触摸屏
		{
			if(myevent.code==ABS_X) //X坐标
			{
				ts_x=(800*myevent.value)/1024;
				cout<<ts_x<<endl;
			}
			if(myevent.code==ABS_Y) //Y坐标
			{
				ts_y=(480*myevent.value)/600;
				cout<<ts_y<<endl;	
			}
		}
	}
}

//线程移动蛇
void *snakemove(void *argv) 
{
	while(1)
	{
		game1.update();
	}
}

int main()
{
	//以获取系统时间的函数作为随机数种子
	srand(time(NULL));
	
	pthread_t tsid;
	pthread_t snakeid;
	
	//打开触摸屏的驱动
	tsfd=open("/dev/input/event0",O_RDWR);
	if(tsfd==-1)
	{
		printf("打开触摸屏失败!\n");
		return -1;
	}
	
	game1.init(); //初始化游戏界面
	
	//创建线程读取触摸屏坐标
	pthread_create(&tsid,NULL,readts,NULL);
	pthread_create(&snakeid,NULL,snakemove,NULL);
	
	while(1)
	{
		if(ts_x>600&&ts_x<690&&ts_y>185&&ts_y<275) //开始游戏
		{
			cout<<"新游戏"<<endl;
			// game1.init();
			game1.setstate();
			game1.show_snakespeed();
			ts_x=0;
			ts_y=0;
			show_anybmp(80,80,600,185,"./zt.bmp");
			break;
		}	
	}
	//进入死循环判断触摸屏点击坐标位置
	while(1)
	{
		if(ts_x>600&&ts_x<690&&ts_y>185&&ts_y<275)
		{
			game1.setstate();
			show_anybmp(80,80,600,185,"./jx.bmp");
			ts_x=0;
			ts_y=0;
		}

		if(ts_x>620&&ts_x<665&&ts_y>295&&ts_y<350)//上
		{
			game1.input_diretion(1);
			ts_x=0;
			ts_y=0;
		}
		if(ts_x>620&&ts_x<665&&ts_y>380&&ts_y<440)//下
		{
			game1.input_diretion(2);
			ts_x=0;
			ts_y=0;
		}
		if(ts_x>515&&ts_x<580&&ts_y>385&&ts_y<430)//左
		{
			game1.input_diretion(4);
			ts_x=0;
			ts_y=0;
		}
		if(ts_x>700&&ts_x<770&&ts_y>385&&ts_y<430)//右
		{
			game1.input_diretion(5);
			ts_x=0;
			ts_y=0;
		}
			if(ts_x>520&&ts_x<575&&ts_y>310&&ts_y<340)//减速
		{
			game1.input_speed(500*100);
			game1.show_snakespeed();
			ts_x=0;
			ts_y=0;
		}
		if(ts_x>710&&ts_x<765&&ts_y>310&&ts_y<340)//加速
		{
			game1.input_speed(-500*100);
			game1.show_snakespeed();
			ts_x=0;
			ts_y=0;
		}
		
	}
	return 0;
}
